/* File name: hello.c
 * * C source file.
 * */
#include "hello.h"
#include "test.h"

#include "event2/event.h"
#include "event2/event_compat.h"

#include <malloc.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <event.h>
#include <netinet/in.h>
#include <asm-generic/socket.h>

#define PORT 10000
#define BACKLOG 5
#define MEM_SIZE 1024
struct event_base  *base; //apply for a mem,events is addresses name

void on_write(int sock, short event, void *args)
{
    char* buffer = (char *)args;
    send(sock, buffer, strlen(buffer), 0);
    free(buffer);
}

void on_read(int sock, short event, void* args)
{
    struct event* write_ev;
    int size;
    char* buffer = (char*)malloc(MEM_SIZE);
    bzero(buffer, MEM_SIZE);
    size = recv(sock, buffer, MEM_SIZE, 0);
    printf("receive data %s, size:%d\n", buffer, size);
    if(size == 0)
    {
        event_del((struct event *)args);
        free((struct event *)args);
        close(sock);
        return;
    }
    write_ev = (struct event *)malloc(sizeof(struct event));
    event_set(write_ev, sock, EV_WRITE, on_write, buffer);
    event_base_set(base, write_ev);
    event_add(base, NULL);

}
void on_accept(int sock, short event, void *args)
{
    struct sockaddr_in cli_addr;
    int newfd, sin_size;
    struct event* read_ev = (struct event *)malloc(sizeof(struct event));
    sin_size = sizeof(struct sockaddr_in);
    newfd = accept(sock, (struct sockaddr *)&cli_addr, &sin_size);
    event_set(read_ev, newfd, EV_READ|EV_PERSIST, on_read, read_ev);
    event_base_set(base, read_ev);
    event_add(read_ev, NULL);
}

void print_hello()
{
    struct sockaddr_in my_addr;
    puts( "Hello, world!" );
    int s = socket(PF_INET, SOCK_STREAM, 0);
    if(s<0){
        perror("socket error");
    }
    /* *
     *bind()
    */
    int yes = 1;
    setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));

    memset(&my_addr, 0, sizeof(my_addr));

    my_addr.sin_family = AF_INET;
    my_addr.sin_port = htons(PORT);
    my_addr.sin_addr.s_addr = htonl(INADDR_ANY);

    bind(s, (struct sockaddr *)&my_addr, sizeof(struct sockaddr));

    listen(s, BACKLOG);
    
    struct event* listen_ev;
    base = event_base_new();

    event_set(listen_ev, s, EV_READ|EV_PERSIST, on_accept, NULL);
    event_base_set(base, listen_ev);         
    event_add(listen_ev, NULL);
    event_base_dispatch(base);

}
